﻿using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using YaAppoint.Appointments.Schedules;
using YaAppoint.Appointments.Schedules.TimeIntervals;
using YaAppoint.Response;

namespace YaAppoint.Appointments.TimeIntervals
{
    /// <summary>
    /// 预约时段服务
    /// </summary>
    [RemoteService(isEnabled: false)]
    public class TimeIntervalAppService(IRepository<TimeInterval,Guid> timeIntervalRepository,
                                        IRepository<Schedule,Guid> scheduleRepository,
                                        TimeIntervalManager timeIntervalManager,
                                        AsyncQueryableExecuter queryableExecuter,
                                        IMapper mapper) : ApplicationService, ITimeIntervalAppService, ITransientDependency
    {
        private readonly IRepository<TimeInterval, Guid> _timeIntervalRepository = timeIntervalRepository;
        private readonly IRepository<Schedule, Guid> _scheduleRepository = scheduleRepository;
        private readonly TimeIntervalManager _timeIntervalManager= timeIntervalManager;
        private readonly AsyncQueryableExecuter _queryableExecuter = queryableExecuter;
        private readonly IMapper _mapper = mapper;

       

        /// <summary>
        /// 删除
        /// </summary>
        public async Task<BackJson> Delete(Guid id)
        {
            await _timeIntervalRepository.DeleteAsync(id);
            return new BackJson()
            {
                code = 0,
                msg = "删除成功"
            };
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        public async Task<BackJson> DeleteMany(List<Guid> idList)
        {
            await _timeIntervalRepository.DeleteManyAsync(idList);
            return new BackJson()
            {
                code = 0,
                msg = "删除成功"
            };
        }

        /// <summary>
        /// 启用/禁用
        /// </summary>
        public async Task<BackJson> DisableToggle(Guid id)
        {
            var timeInterval = await _timeIntervalRepository.FirstOrDefaultAsync(x => x.Id == id);
            if (timeInterval == null)
            {
                throw new BusinessException(CustomErrorCodes.TimeIntervalNotExist);
            }
            string msg = "已启用";
            if (timeInterval.IsActive)
            {
                msg = "已禁用";
            }
            timeInterval.IsActive = !timeInterval.IsActive;
            await _timeIntervalRepository.UpdateAsync(timeInterval);
            return new BackJson()
            {
                code=0,
                msg=msg
            };
        }

        /// <summary>
        /// 获取详情
        /// </summary>
        public async Task<BackJson> GetAsync(Guid id)
        {
            var timeInterval = await _timeIntervalRepository.FirstOrDefaultAsync(x => x.Id == id);
            if (timeInterval == null)
            {
                throw new BusinessException(CustomErrorCodes.TimeIntervalNotExist);
            }
            return new BackJson()
            {
                code = 0,
                data = _mapper.Map<TimeInterval, TimeIntervalDto>(timeInterval)
            };
        }

        /// <summary>
        /// 获取列表
        /// </summary>
        public async Task<BackJson> GetListAsync(Guid sid, string? filterName, int page, int pageSize)
        {
            var query = await _timeIntervalRepository.GetQueryableAsync();
            query = query.Where(t => t.ScheduleId == sid);
            if (!string.IsNullOrEmpty(filterName))
            {
                query=query.Where(t => t.Name.Contains(filterName) || t.Code.Contains(filterName));
            }
            query = query.OrderBy(t => t.StartTime);
            var total = await _queryableExecuter.CountAsync(query);
            query = query.Skip(pageSize * (page - 1)).Take(pageSize);
            var list = await _queryableExecuter.ToListAsync(query);
            return new BackJson()
            {
                code = 0,
                data = new
                {
                    total = total,
                    list = _mapper.Map<List<TimeInterval>, List<TimeIntervalDto>>(list)
                }
            };
        }

        /// <summary>
        /// 提交新建
        /// </summary>
        public async Task<BackJson> SubmitCreate(CreateTimeIntervalDto dto, Guid sid)
        {
            var schedule = await _scheduleRepository.FirstOrDefaultAsync(s => s.Id == sid);
            if (schedule == null)
            {
                throw new BusinessException(CustomErrorCodes.ScheduleNotExist);
            }
            var interval = _mapper.Map<CreateTimeIntervalDto, TimeInterval>(dto);
            if (!string.IsNullOrEmpty(dto.Code))
            {
                var sameCodeList = await _timeIntervalRepository.GetListAsync(t => t.ScheduleId == sid && t.Code.Equals(dto.Code));
                if (sameCodeList.Count > 0)
                {
                    throw new BusinessException(CustomErrorCodes.CodeAlreadyExist)
                    {
                       Data = { 
                            { "code", dto.Code }
                       }
                    };
                }
            }
            await _timeIntervalRepository.InsertAsync(interval);
            return new BackJson()
            {
                code=0,
                msg="保存成功"
            };
        }

        /// <summary>
        /// 批量生成
        /// </summary>
        public async Task<BackJson> BatchCreateAsync(BatchCreateDto batchModel, Guid sid)
        {
            var schedule = await _scheduleRepository.FirstOrDefaultAsync(t=>t.Id==sid);
            if (schedule == null)
            {
                throw new BusinessException(CustomErrorCodes.ScheduleNotExist);
            }
            var wholeInterval = batchModel.EndTime - batchModel.StartTime;
            int count=Convert.ToInt32( wholeInterval.TotalSeconds )/(batchModel.Interval*60);
            int order = count - 1;
            TimeSpan startTime = batchModel.StartTime;
            for (int i = 1; i <= count; i++)
            {
                var timeInterval = new TimeInterval();
                timeInterval.StartTime= startTime;
                timeInterval.EndTime = startTime + TimeSpan.FromMinutes(batchModel.Interval);
                timeInterval.Name = _timeIntervalManager.GenerateName(timeInterval);
                timeInterval.Order = order;
                timeInterval.IsActive = true;
                timeInterval.ScheduleId = sid;
                timeInterval.Name = _timeIntervalManager.GenerateName(timeInterval);
                await _timeIntervalRepository.InsertAsync(timeInterval);
                order--;
                startTime = startTime + TimeSpan.FromMinutes(batchModel.Interval);
            }
            return new BackJson()
            {
                code = 0,
                msg = "批量新建成功"
            };
        }


        /// <summary>
        /// 提交编辑
        /// </summary>
        public async Task<BackJson> SubmitEidt(TimeIntervalDto dto)
        {
            var interval = await _timeIntervalRepository.FirstOrDefaultAsync(t => t.Id == dto.Id);
            if (interval == null)
            {
                throw new BusinessException(CustomErrorCodes.TimeIntervalNotExist);
            }
            if (!string.IsNullOrEmpty(dto.Code))
            {
                var sameCodeList = await _timeIntervalRepository.GetListAsync(t => t.Id != dto.Id && t.Code.Equals(dto.Code)&& t.ScheduleId==dto.ScheduleId);
                if (sameCodeList.Count > 0)
                {
                    throw new BusinessException(CustomErrorCodes.CodeAlreadyExist)
                    {
                        Data = {
                            { "code",dto.Code}
                        }
                    };
                }
            }
            
            interval.Name = dto.Name== null?"":dto.Name;
            interval.StartTime =TimeSpan.Parse(dto.StartTime);
            interval.EndTime = TimeSpan.Parse(dto.EndTime);
            if (string.IsNullOrEmpty(dto.Name))
            {
                interval.Name = _timeIntervalManager.GenerateName(interval);
            }
            interval.Code = dto.Code;
            interval.IsActive = dto.IsActive;
            interval.Order = dto.Order;
            await _timeIntervalRepository.UpdateAsync(interval);
            return new BackJson()
            {
                code = 0,
                msg = "保存成功"
            };
        }
    }
}
